package com.springboot.base.czpreview.controller;

import com.springboot.base.czpreview.config.LibOfficeCoverConfig;
import lombok.var;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDPageContentStream;
import org.apache.pdfbox.pdmodel.font.PDType1Font;
import org.apache.pdfbox.pdmodel.graphics.state.PDExtendedGraphicsState;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.util.HSSFColor;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.model.StylesTable;
import org.apache.poi.xssf.usermodel.XSSFCellStyle;
import org.apache.poi.xssf.usermodel.XSSFColor;
import org.apache.poi.xssf.usermodel.XSSFFont;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.jodconverter.core.DocumentConverter;
import org.jodconverter.core.document.DefaultDocumentFormatRegistry;
import org.jodconverter.core.job.ConversionJob;
import org.jodconverter.core.office.OfficeException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.util.Base64Utils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URL;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.util.List;
import java.util.UUID;

/**
 * @author: 船长
 * @create: 2025-03-25 22:06
 **/

@RequestMapping("/test")
@RestController
public class TestController {


    @Value("${filePreviewPath}")
    private String path;
    @Resource
    private DocumentConverter documentConverter;

    @GetMapping("/a")
    public String a() {
        return "a";
    }

    @PostMapping("/upload")
    public String handleFileUpload(MultipartFile file) throws OfficeException, OfficeException {
        if (file.isEmpty()) {
            return "请选择上传文件";
        }

        // 保存上传文件
        File localFile = new File(path + file.getOriginalFilename());
        try (OutputStream os = new FileOutputStream(localFile)) {
            os.write(file.getBytes());
        } catch (IOException e) {
            e.printStackTrace();
        }

        // 转换成pdf的名称
        String pdfName = UUID.randomUUID().toString().replace("-", "");
        // 转换成pdf存放路径
        File pdfFile = new File(path + pdfName + ".pdf");
        // 开始转换
        documentConverter.convert(localFile)
                .as("doc".equals(DefaultDocumentFormatRegistry.DOC.getExtension()) ? DefaultDocumentFormatRegistry.DOC : DefaultDocumentFormatRegistry.DOCX)
                .to(pdfFile).as(DefaultDocumentFormatRegistry.PDF)
                .execute();

        // 返回转换后的pdf文件的URL
        String previewUrl = "http://localhost:3333/test/preview/" + pdfName;
        return previewUrl;
    }

    /*
    @GetMapping("/preview/{fileName}")
    public void showPreview(@PathVariable String fileName, HttpServletResponse response) throws IOException {
        File file = new File(path + fileName + ".pdf");
        response.setContentType("application/pdf");
        response.setHeader("Content-Disposition", "inline; filename=" + fileName);
        response.setHeader("Content-Length", String.valueOf(file.length()));
        Files.copy(file.toPath(), response.getOutputStream());
    }
     */

    /**
     * 预览pdf
     *
     * @param fileUrl
     * @param response
     * @throws IOException
     */
    @GetMapping("/preview")
    public void showPreview(@RequestParam String fileUrl, @RequestParam(required = false) String watermarkText,
                            HttpServletResponse response) throws IOException, InterruptedException, OfficeException {
        // 补全 fileUrl 协议部分
        fileUrl = ensureProtocol(fileUrl);

        // 对 fileUrl 进行编码处理
        fileUrl = encodeUrl(fileUrl);

        // 获取文件扩展名
        String fileName = new URL(fileUrl).getFile();
        String extension = fileName.substring(fileName.lastIndexOf(".") + 1).toLowerCase();

        // 下载文件到临时目录
        Path tempFile = Files.createTempFile("input-", "." + extension);
        try (InputStream in = new URL(fileUrl).openStream()) {
            Files.copy(in, tempFile, StandardCopyOption.REPLACE_EXISTING);
        }

        // 根据文件类型处理
        Path outputFile = Paths.get("E:Ajava/temp");
        switch (extension) {
            case "doc":
            case "docx":
                outputFile = convertToPdfWithJodConverter(tempFile, extension);
            case "xls":
            case "xlsx":
                outputFile = convertExcelToHtml(tempFile);
                sendFileAsResponse(outputFile, "text/html", fileName.replace("." + extension, ".html"), response);
                return; // 直接返回 HTML 文件
            case "pptx":
                // 转换为 PDF
                outputFile = convertToPdfWithJodConverter(tempFile, extension);
                break;
            case "pdf":
                // 直接使用原始文件
                outputFile = tempFile;
                break;
            case "jpg":
            case "jpeg":
            case "png":
            case "gif":
                // 图片文件直接返回
                sendFileAsResponse(tempFile, getContentType(extension), fileName, response);
                return;
            default:
                throw new IllegalArgumentException("不支持的文件类型: " + extension);
        }
        // 添加水印（如果提供了水印文本）
//        if (watermarkText != null && !watermarkText.isEmpty()) {
//            Path watermarkedFile = Files.createTempFile("watermarked-", ".pdf");
//            addWatermarkToPdf(outputFile, watermarkedFile, watermarkText);
//            outputFile = watermarkedFile;
//        }
        // 设置响应头并返回 PDF 文件
        sendFileAsResponse(outputFile, "application/pdf", fileName.replace("." + extension, ".pdf"), response);

        // 删除临时文件
        Files.deleteIfExists(tempFile);
        if (!outputFile.equals(tempFile)) {
            Files.deleteIfExists(outputFile);
        }
    }

    // 使用 JODConverter 将文件转换为 PDF
    private Path convertToPdfWithJodConverter(Path inputFile, String extension) throws IOException, OfficeException {
        Path outputFile = Files.createTempFile("output-", ".pdf");

        // 获取对应的输入格式
        var inputFormat = DefaultDocumentFormatRegistry.getFormatByExtension(extension);
        if (inputFormat == null) {
            throw new IllegalArgumentException("不支持的文件类型: " + extension);
        }

        // 执行转换
        documentConverter.convert(inputFile.toFile())
                .as(inputFormat)
                .to(outputFile.toFile())
                .as(DefaultDocumentFormatRegistry.PDF)
                .execute();

        return outputFile;
    }

    // 使用 PDFBox 添加水印
    private void addWatermarkToPdf(Path inputFile, Path outputFile, String watermarkText) throws IOException {
        try (PDDocument document = PDDocument.load(inputFile.toFile())) {
            for (PDPage page : document.getPages()) {
                try (PDPageContentStream contentStream = new PDPageContentStream(document, page, PDPageContentStream.AppendMode.APPEND, true, true)) {
                    // 设置透明度
                    PDExtendedGraphicsState graphicsState = new PDExtendedGraphicsState();
                    graphicsState.setNonStrokingAlphaConstant(0.3f); // 设置透明度为 50%
                    contentStream.setGraphicsStateParameters(graphicsState);

                    // 设置字体和颜色
                    contentStream.setFont(PDType1Font.HELVETICA_BOLD, 20);
                    contentStream.setNonStrokingColor(249, 66, 66); // 浅灰色

                    // 获取页面尺寸
                    float pageWidth = page.getMediaBox().getWidth();
                    float pageHeight = page.getMediaBox().getHeight();

                    // 计算水印位置（居中）
                    float fontSize = 48;
                    float stringWidth = PDType1Font.HELVETICA_BOLD.getStringWidth(watermarkText) / 1000 * fontSize;
                    float x = (pageWidth - stringWidth) / 2;
                    float y = pageHeight / 2;

                    // 绘制水印文本
                    contentStream.beginText();
                    contentStream.newLineAtOffset(x, y);
                    contentStream.showText(watermarkText);
                    contentStream.endText();
                }
            }

            // 保存带水印的 PDF 文件
            document.save(outputFile.toFile());
        }
    }

    private Path convertExcelToHtml(Path excelFilePath) throws IOException {
        Path htmlFilePath = Files.createTempFile("output-", ".html");

        try (InputStream inputStream = new FileInputStream(excelFilePath.toFile());
             Workbook workbook = WorkbookFactory.create(inputStream)) { // 自动检测文件格式

            StringBuilder htmlContent = new StringBuilder();
            htmlContent.append("<!DOCTYPE html>")
                    .append("<html><head>")
                    .append("<meta charset='UTF-8'>")
                    .append("<style>")
                    // 定义全局样式
                    .append("body { font-family: Arial, sans-serif; }")
                    .append(".sheet-tabs { display: flex; margin-bottom: 20px; }")
                    .append(".sheet-tab { padding: 10px 20px; cursor: pointer; border: 1px solid #ddd; background-color: #f9f9f9; }")
                    .append(".sheet-tab.active { background-color: #007bff; color: white; }")
                    .append(".sheet-content { display: none; }")
                    .append(".sheet-content.active { display: block; }")
                    .append("table { border-collapse: collapse; width: 100%; margin-bottom: 20px; }")
                    .append("th, td { border: 1px solid #ddd; padding: 8px; text-align: left; }")
                    .append("th { background-color: #f2f2f2; font-weight: bold; }")
                    .append("</style>")
                    .append("<script>")
                    // JavaScript 实现 Tab 切换
                    .append("function switchSheet(sheetId) {")
                    .append("  const tabs = document.querySelectorAll('.sheet-tab');")
                    .append("  const contents = document.querySelectorAll('.sheet-content');")
                    .append("  tabs.forEach(tab => tab.classList.remove('active'));")
                    .append("  contents.forEach(content => content.classList.remove('active'));")
                    .append("  document.getElementById('tab-' + sheetId).classList.add('active');")
                    .append("  document.getElementById('content-' + sheetId).classList.add('active');")
                    .append("}")
                    .append("</script>")
                    .append("</head><body onload=\"switchSheet(0)\">") // 页面加载时默认选中第一个 Tab
            ;

            // 添加 Sheet Tab
            htmlContent.append("<div class='sheet-tabs'>");
            for (int i = 0; i < workbook.getNumberOfSheets(); i++) {
                Sheet sheet = workbook.getSheetAt(i);
                htmlContent.append("<div class='sheet-tab' id='tab-").append(i)
                        .append("' onclick='switchSheet(").append(i).append(")'>")
                        .append(sheet.getSheetName()).append("</div>");
            }
            htmlContent.append("</div>");

            // 添加 Sheet 内容
            for (int i = 0; i < workbook.getNumberOfSheets(); i++) {
                Sheet sheet = workbook.getSheetAt(i);
                htmlContent.append("<div class='sheet-content' id='content-").append(i).append("'")
                        .append(i == 0 ? " class='sheet-content active'" : "").append(">"); // 默认显示第一个 Sheet
                htmlContent.append("<table>");

                // 获取所有合并区域
                List<CellRangeAddress> mergedRegions = sheet.getMergedRegions();

                for (Row row : sheet) {
                    htmlContent.append("<tr>");
                    int lastProcessedCol = -1;

                    for (Cell cell : row) {
                        int currentColIndex = cell.getColumnIndex();

                        // 跳过已经处理的列（属于合并区域的内部单元格）
                        if (currentColIndex <= lastProcessedCol) {
                            continue;
                        }

                        boolean isMergedCell = false;
                        int colspan = 1;
                        int rowspan = 1;

                        // 检查当前单元格是否属于某个合并区域
                        for (CellRangeAddress region : mergedRegions) {
                            if (isCellInRegion(cell, region)) {
                                if (cell.getRowIndex() == region.getFirstRow() && cell.getColumnIndex() == region.getFirstColumn()) {
                                    // 只在合并区域的左上角单元格添加 colspan 和 rowspan
                                    colspan = region.getLastColumn() - region.getFirstColumn() + 1;
                                    rowspan = region.getLastRow() - region.getFirstRow() + 1;
                                    isMergedCell = true;
                                    break;
                                }
                            }
                        }

                        // 添加单元格内容
                        htmlContent.append("<td");
                        if (colspan > 1) {
                            htmlContent.append(" colspan='").append(colspan).append("'");
                        }
                        if (rowspan > 1) {
                            htmlContent.append(" rowspan='").append(rowspan).append("'");
                        }
                        htmlContent.append(">");
                        htmlContent.append(getCellValue(cell));
                        htmlContent.append("</td>");

                        // 更新已处理的列索引
                        lastProcessedCol = currentColIndex + colspan - 1;
                    }
                    htmlContent.append("</tr>");
                }
                htmlContent.append("</table></div>");
            }

            htmlContent.append("</body></html>");

            // 写入 HTML 文件
            Files.write(htmlFilePath, htmlContent.toString().getBytes(StandardCharsets.UTF_8));
        }

        return htmlFilePath;
    }

    // 判断单元格是否属于某个合并区域
    private boolean isCellInRegion(Cell cell, CellRangeAddress region) {
        int rowIndex = cell.getRowIndex();
        int colIndex = cell.getColumnIndex();
        return rowIndex >= region.getFirstRow() && rowIndex <= region.getLastRow() &&
                colIndex >= region.getFirstColumn() && colIndex <= region.getLastColumn();
    }

    // 获取单元格的值
    private String getCellValue(Cell cell) {
        switch (cell.getCellType()) {
            case STRING:
                return cell.getStringCellValue();
            case NUMERIC:
                if (DateUtil.isCellDateFormatted(cell)) {
                    return cell.getDateCellValue().toString();
                } else {
                    return String.valueOf(cell.getNumericCellValue());
                }
            case BOOLEAN:
                return String.valueOf(cell.getBooleanCellValue());
            case FORMULA:
                return cell.getCellFormula();
            default:
                return "";
        }
    }


    // 补全协议部分
    private String ensureProtocol(String url) {
        if (!url.startsWith("http://") && !url.startsWith("https://")) {
            return "http://" + url;
        }
        return url;
    }

    // 对 URL 进行编码处理
    private String encodeUrl(String url) throws UnsupportedEncodingException {
        String protocol = "";
        String hostAndPath = url;

        if (url.contains("://")) {
            int index = url.indexOf("://");
            protocol = url.substring(0, index + 3);
            hostAndPath = url.substring(index + 3);
        }

        String encodedHostAndPath = URLEncoder.encode(hostAndPath, "UTF-8")
                .replaceAll("\\+", "%20")
                .replaceAll("%3A", ":")
                .replaceAll("%2F", "/");

        return protocol + encodedHostAndPath;
    }

    // 发送文件作为响应
    private void sendFileAsResponse(Path filePath, String contentType, String fileName, HttpServletResponse response) throws IOException {
        response.setContentType(contentType);
        response.setHeader("Content-Disposition", "inline; filename=" + fileName);
        response.setHeader("Content-Length", String.valueOf(Files.size(filePath)));

        try (OutputStream out = response.getOutputStream()) {
            Files.copy(filePath, out);
        }
    }

    // 获取图片的 MIME 类型
    private String getContentType(String extension) {
        switch (extension.toLowerCase()) {
            case "jpg":
            case "jpeg":
                return "image/jpeg";
            case "png":
                return "image/png";
            case "gif":
                return "image/gif";
            default:
                return "application/octet-stream";
        }
    }
}
